#pragma once
#include "DcmParser.h"

#include <string>
#include <vector>
#include <mutex>

enum IMAGETYPE
{
	IT_UNKNOWN,
	IT_DCM,
	IT_BMP,
	IT_JPG,
	IT_PNG,
	IT_GIF,
	IT_TIFF,
	IT_PDF,
	
};

struct PatientInfo
{
    std::string patId;              // (0010,0020) LO Patient ID
    std::string patName;            // (0010,0010) PN Patient's Name
    std::string sex;                // (0010,0040) CS Patient's Sex
    std::string birthday;           // (0010,0030) DA Patient's Birth Date
    std::string studyAge;           // (0010,1010) AS Patient's Age
	float  patWeight;              // (0010,1030) DS Patient's Weight
};

struct StudyInfo 
{
    std::string studyInsUid;        // (0020,000D) UI Study Instance UID
    std::string studyDesc;          // (0008,1030) LO Study Description
    std::string studyId;            // (0020,0010) SH Study ID
    std::string accessionNumber;    // (0008,0050) SH Accession Number
    std::string studyDate;          // (0008,0020) DA Study Date
    std::string studyTime;          // (0008,0030) TM Study Time
    std::string modality;           // (0008,0060) CS Modality
    std::string manufacturer;       // (0008,0070) LO Manufacturer
    std::string hospitalName;       // (0008,0080) LO Institution Name
    std::string hospitalAddr;       // (0008,0081) ST Institution Address
    std::string operatorName;       // (0008,1070) PN Operators' Name
	
};

struct SeriesInfo
{
    std::string seriesInsUid;       // (0020,000E) UI Series Instance UID
    std::string seriesDesc;         // (0008,103E) LO Series Description
    std::string seriesDate;         // (0008,0021) DA Series Date
    std::string seriesTime;         // (0008,0031) TM Series Time
	int    seriesNumber;           // (0020,0011) IS Series Number
	
	// CT
    std::string   kvp;                 // (0018,0060) DS KVP
    std::string   exposureTime;        // (0018,1150) IS Exposure Time
    std::string   xRayTubeCurrent;     // (0018,1151) IS X-Ray Tube Current
    std::string   exposure;            // (0018,1152) IS Exposure

	// MR
    std::string  percentFOV;         // (0018,0094) DS  Percent Phase Field of View
    std::string  TR;                 // (0018,0080) DS  Repetition Time;
    std::string  TE;                 // (0018,0081) DS  Echo Time;
    std::string  FS;                 // (0018,0087) DS  Magnetic Field Strength;
	int    amiX;               // (0018,1310) US 0 Acquisition Matrix
	int    amiY;               // (0018,1310) US 1 Acquisition Matrix
	int    amjX;               // (0018,1310) US 2 Acquisition Matrix
	int    amjY;               // (0018,1310) US 3 Acquisition Matrix
    std::string protocolName;       // (0018,1030) LO Protocol Name
    std::string scanSequence;   // (0018,0020) CS Scanning Sequence

};

struct ImageInfo 
{
	float ipX;                 // (0020,0032) DS 0 Image Position(Patient)
	float ipY;                 // (0020,0032) DS 1 Image Position(Patient)
	float ipZ;                 // (0020,0032) DS 2 Image Position(Patient)
	float ioiX;                // (0020,0037) DS 0 Image Orientation(Patient)
	float ioiY;                // (0020,0037) DS 1 Image Orientation(Patient)
	float ioiZ;                // (0020,0037) DS 2 Image Orientation(Patient)
	float iojX;                // (0020,0037) DS 3 Image Orientation(Patient)
	float iojY;                // (0020,0037) DS 4 Image Orientation(Patient)
	float iojZ;                // (0020,0037) DS 5 Image Orientation(Patient)
    std::string poX;            // (0020,0020) DS 0 Patient Orientation
    std::string poY;            // (0020,0020) DS 1 Patient Orientation
    std::string patPosition;    // (0018,5100) CS   Patient Position
                  
    std::string sliceThickness;      // (0018,0050) DS Slice Thickness
    std::string sliceLocation;       // (0020,1041) DS Slice Location
	int   samplePerPixel;      // (0028,0002) US Samples per Pixel
	float psX;                 // (0028,0030) DS 0 Pixel Spacing
	float psY;                 // (0028,0030) DS 1 Pixel Spacing
	int bitsAlloc;             // (0028,0100) US Bits Allocated
	int bitsStored;			   // (0028,0101) US Bits Stored
	int hightBit;			   // (0028,0102) US High Bit
	int pixelRep;              // (0028,0103) US Pixel Representation
	float defWinCenter;        // (0028,1050) DS Window Center
	float defWinWidth;         // (0028,1051) DS Window Width
	float rescaleIntercept;    // (0028,1052) DS Rescale Intercept
	float rescaleSlope;        // (0028,1053) DS Rescale Slope
	int height;                // (0028,0010) US Rows
	int width;                 // (0028,0011) US Columns
	int instanceNumber;        // (0020,0013) IS Instance Number

    std::string sopInsUid;          // (0008,0018) UI SOP Instance UID
    std::string xfer;               // (0002,0010) UI Transfer Syntax UID
    std::string imageType;          // (0008,0008) CS Image Type
    std::string charset;            // (0008,0005) CS Specific Character Set
    std::string contentDate;        // (0008,0023) DA Content Date
    std::string contentTime;        // (0008,0033) TM Content Time
    std::string acquisitionDate;    // (0008,0022) DA Acquisition Date
    std::string acquisitionTime;    // (0008,0032) TM Acquisition Time
};

class CBaseImage
{
public:
	CBaseImage();
	virtual ~CBaseImage();

public:
	PatientInfo& GetPatientInfo();
	StudyInfo&   GetStudyInfo();
	SeriesInfo&  GetSeriesInfo();
    ImageInfo&   GetImageInfo();

    virtual int ParseFile(std::string fn)=0;
	virtual void Close() = 0;
    virtual int ReParseFile() = 0;
	virtual void GetDefaultWindow(double& wc, double& ww) = 0;
    virtual int CreateDIB(void*& pdib, int& w, int& h, int wc, int ww, int frame = 0, bool bneg = false) = 0;

	virtual std::string GetFileName() { return m_fileName; }
    virtual int IsValid() { return m_bParserValid; }
	virtual int GetFrameCount() { return 1; }
    virtual void GetRange(double& minVal, double& maxVal) = 0;
	virtual bool Export(std::string dst, int format) {
		return false;
	}


	DcmParser* GetParser() { return &m_parser; }

protected:
	PatientInfo m_patInfo;
	StudyInfo   m_studyInfo;
	SeriesInfo  m_seriesInfo;
    ImageInfo   m_imageInfo;

    int         m_bParserValid;
	std::string	m_fileName;
	DcmParser   m_parser;

};

